package ar.edu.utn.xcontainer;
import java.util.Hashtable;
import java.util.List;

import ar.edu.utn.exceptions.ReflectionException;
import ar.edu.utn.injectors.ConstructorArguments;
import ar.edu.utn.injectors.Parameter;
import ar.edu.utn.injectors.SetterPrymitiveInyector;

public class ComposeComponentDescription {
	
	private String componentKey;
	private String className;
	private ConstructorArguments constructorArguments;
	private Container container;
	private SetterPrymitiveInyector inyector; /*Esto no va as�*/
	
	
	private Hashtable<String,Object> primitiveProperty;
	private Object instance;
	

	/**
	 * @param <T>
	 * @param <T>
	 * @param args
	 * @return 
	 * @throws ClassNotFoundException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	
	
	public ComposeComponentDescription(Container container){
		this.container=container;
		this.constructorArguments=new ConstructorArguments();
		this.primitiveProperty=new Hashtable<String,Object>();
		this.inyector=new SetterPrymitiveInyector();
	}
	
	public ComposeComponentDescription(String key,String clazz, Container container){
		this.container=container;
		this.constructorArguments=new ConstructorArguments();
		this.primitiveProperty=new Hashtable<String,Object>();
		this.inyector=new SetterPrymitiveInyector();
		this.componentKey=key;
		this.className=clazz;
	}
	
	/*Esto deberia ir en otra clase*/
	public void addConstructorArgument(String type, Object value){
		Parameter parameter=new Parameter(type, value);
		this.constructorArguments.addParameter(parameter);
	}
	
	public List<Parameter> getConstructorArguments(){
		return this.constructorArguments.getArguments();
	}
	public ConstructorArguments getClassConstructorArguments(){
		return this.constructorArguments;
	}
		
		
	

	public Object getInstanceComponent() throws ReflectionException{
		if (this.instance==null){
			 Object componentInstance;
			try {
				componentInstance = this.instance=getComponentClass().newInstance();
				this.inyector.inyect(componentInstance, primitiveProperty);
			//TODO para mi hay que extraer a un instanciador generico para evitar estos
			//TODO catch pedorros
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return this.instance;
		 
		}
	
	public String getComponentKey() {
		return componentKey;
	}

	public void setComponentKey(String componentKey) {
		this.componentKey = componentKey;
	}

	
	public Class<?> getComponentClass() throws ReflectionException{
		//TODO al igual que en el metodo de mas arriba, estaria bueno tener
		//TODO un getClass generico para evitar tener que catchearlo todo el tiempo
		Class<?> clazz = null;
		
		try {
			clazz=Class.forName(this.className);
		} catch (ClassNotFoundException e) {
			throw new ReflectionException("No se pudo encontrar la clase", e.getCause());
		}
		
		return clazz;
	}
	
	
	public void disposeComponent(){
	}
	
	
	public void addSimpleDependency(String name, Object value){
		this.primitiveProperty.put(name, value);
	}

}
